package com.jackiepenghe.rangedatepickerlibrary

import android.annotation.SuppressLint
import android.graphics.drawable.Drawable
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.jackiepenghe.rangedatepickerlibrary.listener.OnDateSelectChangedListener
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

/**
 * @author jackie
 */
internal class DataRecyclerViewAdapter :
    RecyclerView.Adapter<DataRecyclerViewAdapter.ViewHolder>() {

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 属性声明
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /* * * * * * * * * * * * * * * * * * * 常量属性 * * * * * * * * * * * * * * * * * * */

    /**
     * 适配器数据源
     */
    private val dataListContainsLastMonth = arrayListOf<Date>()

    private val dataList = arrayListOf<Date>()

    /* * * * * * * * * * * * * * * * * * * 可变属性 * * * * * * * * * * * * * * * * * * */

    internal var dateActiveDate: Date = getCurrentDate()

    internal var startDate: Date? = null

    internal var endDate: Date? = null

    /**
     * 显示 月份信息 的文本的文字大小
     */
    private var dateMonthTextSize = 0f

    /**
     * 显示 月份信息 的文本的文字颜色
     */
    private var dateMonthTextColor = 0

    /**
     * 日期选项的大小
     */
    private var dateItemSize = 0f

    /**
     * 日期选项的item 正常的背景色
     */
    private var dateItemBackgroundNormal: Drawable? = null

    /**
     * 日期选项的item 正常的背景色
     */
    private var dateItemBackgroundSelect: Drawable? = null

    /**
     * 日期选项的item 文本大小
     */
    private var dateItemTextSize = 0f

    /**
     * 日期选项的item 正常文本颜色
     */
    private var dateItemTextColorNormal = 0

    /**
     * 日期选项的item 选中文本颜色
     */
    private var dateItemTextColorSelect = 0

    /**
     * 日期选项的item 未激活(不可选)时文本颜色
     */
    private var dateItemTextColorDisable = 0

    /**
     * 日期选项的item 选中的日期为起始日期时的背景
     */
    private var dateItemBackgroundStart: Drawable? = null

    /**
     * 日期选项的item 选中的日期为结束日期时的背景
     */
    private var dateItemBackgroundEnd: Drawable? = null

    /**
     * 日期选项的item 空白文本的背景
     */
    private var dateItemBackgroundEmpty: Drawable? = null

    /**
     * 日期选项的item 选中的日期为未激活(不可选)时的背景
     */
    private var dateItemBackgroundEndDisable: Drawable? = null


    /**
     * 单选中一个日期时，日期的背景（不设置时，默认与dateItemBackgroundSelect一致）
     */
    private var dateItemBackgroundSingleSelect: Drawable? = null

    /**
     * 是否允许选择激活日期之前的日期
     */
    internal var enableBeforeActiveDate = false

    /**
     * 最大可选的日期数量
     */
    private var dateMaxSelectCount: Int = 0

    /**
     * 是否显示上月份的日期选择器
     */
    private var showLastMonthDate = false

    /**
     * 日期格式化工具
     */
    private var dateMonthFormat = SimpleDateFormat("yyyy年MM月", Locale.CHINA)

    private var onDateSelectChangedListener: OnDateSelectChangedListener? = null

    /**
     * 选择模式
     */
    private var selectMode = RangeDatePickerView.SelectMode.INDEPENDENT

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 构造方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    init {
        val currentDate = getCurrentDate()
        dateActiveDate = currentDate
        dataListContainsLastMonth.add(currentDate.addMonth(-1))
        dataListContainsLastMonth.add(currentDate)
        dataListContainsLastMonth.add(currentDate.addMonth(1))

        dataList.add(currentDate)
        dataList.add(currentDate.addMonth(1))
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 内部类声明
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 实现方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(
                R.layout.com_jackiepenghe_rangedatepickerlibrary_adapter_date_recycler_view,
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val date = if (showLastMonthDate) {
            dataListContainsLastMonth[position]
        } else {
            dataList[position]
        }
        val dateMonthTextView =
            holder.itemView.findViewById<TextView>(R.id.com_jackiepenghe_rangedatepickerlibrary_adapter_date_recycler_view_date_string)
        dateMonthTextView.text =
            dateMonthFormat.format(date)
        dateMonthTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, dateMonthTextSize)
        dateMonthTextView.setTextColor(dateMonthTextColor)
        initRecyclerView(holder, position)
    }

    internal fun refreshDateListener() {
        onDateSelectChangedListener?.onDataSelect(startDate, endDate, getDifferDayCount())
    }

    override fun getItemCount(): Int {
        return if (showLastMonthDate) {
            dataListContainsLastMonth.size
        } else {
            dataList.size
        }
    }
    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 公开方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    internal fun setDateMonthTextSize(dateMonthTextSize: Float) {
        this.dateMonthTextSize = dateMonthTextSize
    }

    internal fun setDateMonthTextColor(dateMonthTextColor: Int) {
        this.dateMonthTextColor = dateMonthTextColor
    }

    internal fun setDateItemSize(dateItemSize: Float) {
        this.dateItemSize = dateItemSize
    }

    internal fun setDateItemBackgroundNormal(dateItemBackgroundNormalColor: Drawable?) {
        this.dateItemBackgroundNormal = dateItemBackgroundNormalColor
    }

    internal fun setDateItemBackgroundSelect(dateItemBackgroundSelectColor: Drawable?) {
        this.dateItemBackgroundSelect = dateItemBackgroundSelectColor
    }

    internal fun setDateItemTextSize(dateItemTextSize: Float) {
        this.dateItemTextSize = dateItemTextSize
    }

    internal fun setDateItemTextColorNormal(dateItemTextColorNormal: Int) {
        this.dateItemTextColorNormal = dateItemTextColorNormal
    }

    internal fun setDateItemTextColorSelect(dateItemTextColorSelect: Int) {
        this.dateItemTextColorSelect = dateItemTextColorSelect
    }

    internal fun setDateItemTextColorDisable(dateItemTextColorDisable: Int) {
        this.dateItemTextColorDisable = dateItemTextColorDisable
    }

    internal fun setDateItemBackgroundStart(dateItemBackgroundStart: Drawable?) {
        this.dateItemBackgroundStart = dateItemBackgroundStart
    }

    internal fun setDateItemBackgroundEnd(dateItemBackgroundEnd: Drawable?) {
        this.dateItemBackgroundEnd = dateItemBackgroundEnd
    }

    internal fun setAllowSelectBeforeActiveDate(allowSelectBeforeActiveDate: Boolean) {
        this.enableBeforeActiveDate = allowSelectBeforeActiveDate
    }

    internal fun setDateItemBackgroundDisable(dateItemBackgroundEndDisable: Drawable?) {
        this.dateItemBackgroundEndDisable = dateItemBackgroundEndDisable
    }

    internal fun setDateMonthFormat(dateMonthFormat: String?) {
        this.dateMonthFormat = if (dateMonthFormat == null) {
            SimpleDateFormat("yyyy年MM月", Locale.CHINA)
        } else {
            SimpleDateFormat(dateMonthFormat, Locale.CHINA)
        }
    }

    internal fun setDateMaxSelectCount(dateMaxSelectCount: Int) {
        this.dateMaxSelectCount = dateMaxSelectCount
    }

    internal fun setShowLastMonthDate(showLastMonthDate: Boolean) {
        this.showLastMonthDate = showLastMonthDate
    }

    internal fun setActiveDate(activeDate: Date) {
        this.dateActiveDate = activeDate
    }

    internal fun setOnDateSelectChangedListener(onDateSelectChangedListener: OnDateSelectChangedListener?) {
        this.onDateSelectChangedListener = onDateSelectChangedListener
    }

    internal fun setDateItemBackgroundEmpty(dateItemBackgroundEmpty: Drawable?) {
        this.dateItemBackgroundEmpty = dateItemBackgroundEmpty
    }

    internal fun setSelectMode(selectMode: Int) {
        this.selectMode = selectMode
    }

    internal fun setDateItemBackgroundSingleSelect(dateItemBackgroundSingleSelect: Drawable?) {
        this.dateItemBackgroundSingleSelect = dateItemBackgroundSingleSelect
    }

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *
     * 私有方法
     *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

    /**
     * 初始化RecyclerView
     */
    private fun initRecyclerView(
        holder: ViewHolder,
        position: Int
    ) {
        val itemDate = if (showLastMonthDate) {
            dataListContainsLastMonth[position]
        } else {
            dataList[position]
        }
        val recyclerView =
            holder.itemView.findViewById<RecyclerView>(R.id.com_jackiepenghe_rangedatepickerlibrary_adapter_date_recycler_view_date_show_rv)
        val gridLayoutManager = GridLayoutManager(recyclerView.context, 7)
        recyclerView.layoutManager = gridLayoutManager
        val dataSelectRecyclerViewAdapter =
            DataSelectRecyclerViewAdapter(
                gridLayoutManager,
                itemDate,
                this,
                object : DataSelectRecyclerViewAdapter.OnItemClickListener {
                    /**
                     * 日期选项被点击了
                     */
                    override fun onItemClicked(
                        position: Int,
                        dateString: String,
                        date: Date,
                        dataSelectRecyclerViewAdapter: DataSelectRecyclerViewAdapter
                    ) {
                        when (selectMode) {
                            RangeDatePickerView.SelectMode.INDEPENDENT -> {
                                handleIndependentMode(dataSelectRecyclerViewAdapter, position, date)
                            }

                            RangeDatePickerView.SelectMode.CONTINUOUS -> {
                                handleContinuousMode(dataSelectRecyclerViewAdapter, position, date)
                            }

                            RangeDatePickerView.SelectMode.SINGLE_SELECT -> {
                                handleSingleMode(dataSelectRecyclerViewAdapter, position, date)
                            }

                            else -> {
                                handleSingleMode(dataSelectRecyclerViewAdapter, position, date)
                            }
                        }
                    }
                })
        dataSelectRecyclerViewAdapter.setDateItemSize(dateItemSize)
        dataSelectRecyclerViewAdapter.setDateItemBackgroundNormal(dateItemBackgroundNormal)
        dataSelectRecyclerViewAdapter.setDateItemBackgroundSelect(dateItemBackgroundSelect)
        dataSelectRecyclerViewAdapter.setDateItemTextSize(dateItemTextSize)
        dataSelectRecyclerViewAdapter.setDateItemTextColorNormal(dateItemTextColorNormal)
        dataSelectRecyclerViewAdapter.setDateItemTextColorSelect(dateItemTextColorSelect)
        dataSelectRecyclerViewAdapter.setDateItemTextColorDisable(dateItemTextColorDisable)
        dataSelectRecyclerViewAdapter.setDateItemBackgroundStart(dateItemBackgroundStart)
        dataSelectRecyclerViewAdapter.setDateItemBackgroundEnd(dateItemBackgroundEnd)
        dataSelectRecyclerViewAdapter.setDateItemBackgroundEmpty(dateItemBackgroundEmpty)
        dataSelectRecyclerViewAdapter.setDateItemBackgroundDisable(dateItemBackgroundEndDisable)
        dataSelectRecyclerViewAdapter.setDateItemBackgroundSingleSelect(
            dateItemBackgroundSingleSelect
        )
        recyclerView.adapter = dataSelectRecyclerViewAdapter
    }

    /**
     * 单选模式的点击事件处理
     */
    @SuppressLint("NotifyDataSetChanged")
    private fun handleSingleMode(
        dataSelectRecyclerViewAdapter: DataSelectRecyclerViewAdapter,
        position: Int,
        date: Date
    ) {

        //选择的日期和开始日期一致，取消选中
        if (date == startDate) {
            this@DataRecyclerViewAdapter.startDate = null
            dataSelectRecyclerViewAdapter.notifyItemChanged(position)
        } else {
            startDate = date
            dataSelectRecyclerViewAdapter.notifyDataSetChanged()
        }
        this@DataRecyclerViewAdapter.notifyDataSetChanged()
        onDateSelectChangedListener?.onDataSelect(
            this@DataRecyclerViewAdapter.startDate,
            this@DataRecyclerViewAdapter.endDate,
            getDifferDayCount()
        )
    }

    /**
     * 连续模式的点击事件处理
     */
    @SuppressLint("NotifyDataSetChanged")
    private fun handleContinuousMode(
        dataSelectRecyclerViewAdapter: DataSelectRecyclerViewAdapter,
        position: Int,
        date: Date
    ) {
        //开始日期为空，将选择的日期作为开始日期
        if (startDate == null) {
            startDate = date
            dataSelectRecyclerViewAdapter.notifyItemChanged(position)
            onDateSelectChangedListener?.onDataSelect(
                startDate,
                endDate,
                getDifferDayCount()
            )
            return
        }
        val startDate = startDate ?: return
        //结束日期为空，设置结束日期
        if (endDate == null) {
            when {
                //选择的日期和开始日期一致，取消选中
                date == startDate -> {
                    this@DataRecyclerViewAdapter.startDate = null
                    dataSelectRecyclerViewAdapter.notifyItemChanged(position)
                }
                //选择的日期在开始日期之前
                date.before(startDate) -> {
                    //计算日期差值，大于设置的最大值不做处理
                    val differDay = startDate.differDay(date)
                    if (differDay > dateMaxSelectCount) {
                        onDateSelectChangedListener?.onDataRangeOutOfMax(
                            date,
                            dateMaxSelectCount,
                            differDay
                        )
                        return
                    }
                    //设置开始与结束日期，并更新界面
                    endDate = startDate
                    this@DataRecyclerViewAdapter.startDate = date
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                }
                //选择的日期在开始日期之后
                else -> {
                    //计算日期差值，大于设置的最大值不做处理
                    val differDay = startDate.differDay(date)
                    if (differDay > dateMaxSelectCount) {
                        onDateSelectChangedListener?.onDataRangeOutOfMax(
                            date,
                            dateMaxSelectCount,
                            differDay
                        )
                        return
                    }
                    //设置结束日期，并更新界面
                    endDate = date
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                }
            }

            onDateSelectChangedListener?.onDataSelect(
                this@DataRecyclerViewAdapter.startDate,
                this@DataRecyclerViewAdapter.endDate,
                getDifferDayCount()
            )
            return
        }
        //开始日期与结束日期都有值
        val endDate = endDate ?: return
        when {
            //点击开始日期
            date == startDate -> {
                //将开始日期后移一天
                val cache = date.addDay(1)
                //判断是否后移之后的日期是否为结束日期
                if (cache == endDate) {
                    //更新起始日期
                    this@DataRecyclerViewAdapter.startDate = cache
                    //清空结束日期
                    this@DataRecyclerViewAdapter.endDate = null
                    //更新界面
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                } else {
                    //更新起始日期
                    this@DataRecyclerViewAdapter.startDate = cache
                    //更新界面
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                }
            }
            //选择的日期为结束日期
            date == endDate -> {
                //将日期前移一天
                val cache = date.addDay(-1)
                //判断前移后的日期是否为开始日期
                if (cache == startDate) {
                    //设置开始日期
                    this@DataRecyclerViewAdapter.startDate = cache
                    //清空结束日期
                    this@DataRecyclerViewAdapter.endDate = null
                    //更新界面
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                } else {
                    //设置结束日期
                    this@DataRecyclerViewAdapter.endDate = cache
                    //更新界面
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                }
            }
            //选择的日期在开始日期之前
            date.before(startDate) -> {
                //计算日期差值（结束日期和当前选择的日期），大于设置的最大值不做处理
                val differDay = endDate.differDay(date)
                if (differDay > dateMaxSelectCount) {
                    onDateSelectChangedListener?.onDataRangeOutOfMax(
                        date,
                        dateMaxSelectCount,
                        differDay
                    )
                    return
                }
                //更新起始日期为选中的日期
                this@DataRecyclerViewAdapter.startDate = date
                //更新界面
                this@DataRecyclerViewAdapter.notifyDataSetChanged()
            }
            //选择的日期在结束日期之后
            date.after(endDate) -> {
                //计算日期差值（起始日期和当前选择的日期），大于设置的最大值不做处理
                val differDay = startDate.differDay(date)
                if (differDay > dateMaxSelectCount) {
                    onDateSelectChangedListener?.onDataRangeOutOfMax(
                        date,
                        dateMaxSelectCount,
                        differDay
                    )
                    return
                }
                //更新结束日期
                this@DataRecyclerViewAdapter.endDate = date
                //更新界面
                this@DataRecyclerViewAdapter.notifyDataSetChanged()
            }
            //选择的日期在起始日期和结束日期之间
            else -> {
                //更新结束日期
                this@DataRecyclerViewAdapter.endDate = date
                //更新界面
                this@DataRecyclerViewAdapter.notifyDataSetChanged()
            }
        }
        onDateSelectChangedListener?.onDataSelect(
            this@DataRecyclerViewAdapter.startDate,
            this@DataRecyclerViewAdapter.endDate,
            getDifferDayCount()
        )
    }

    /**
     * 独立模式的点击事件处理
     */
    @SuppressLint("NotifyDataSetChanged")
    private fun handleIndependentMode(
        dataSelectRecyclerViewAdapter: DataSelectRecyclerViewAdapter,
        position: Int,
        date: Date
    ) {
        //开始日期为空，将选择的日期作为开始日期
        if (startDate == null) {
            startDate = date
            dataSelectRecyclerViewAdapter.notifyItemChanged(position)
            onDateSelectChangedListener?.onDataSelect(
                startDate,
                endDate,
                getDifferDayCount()
            )
            return
        }
        val startDate = startDate ?: return
        //结束日期为空时
        if (endDate == null) {
            when {
                //选择的日期和开始日期一致，取消选中
                date == startDate -> {
                    this@DataRecyclerViewAdapter.startDate = null
                    dataSelectRecyclerViewAdapter.notifyItemChanged(position)
                }
                //选择的日期在开始日期之前
                date.before(startDate) -> {
                    //更新选择的日期为开始日期，并更新界面
                    this@DataRecyclerViewAdapter.startDate = date
                    endDate = null
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                }
                //选择的日期在开始日期之后
                else -> {
                    //计算日期差值，大于设置的最大值不做处理
                    val differDay = startDate.differDay(date)
                    if (differDay > dateMaxSelectCount) {
                        onDateSelectChangedListener?.onDataRangeOutOfMax(
                            date,
                            dateMaxSelectCount,
                            differDay
                        )
                        return
                    }
                    //设置结束日期，并更新界面
                    endDate = date
                    this@DataRecyclerViewAdapter.notifyDataSetChanged()
                }
            }

            onDateSelectChangedListener?.onDataSelect(
                this@DataRecyclerViewAdapter.startDate,
                this@DataRecyclerViewAdapter.endDate,
                getDifferDayCount()
            )
            return
        }
        this@DataRecyclerViewAdapter.startDate = null
        this@DataRecyclerViewAdapter.endDate = null
        this@DataRecyclerViewAdapter.notifyDataSetChanged()
        onDateSelectChangedListener?.onDataSelect(
            this@DataRecyclerViewAdapter.startDate,
            this@DataRecyclerViewAdapter.endDate,
            getDifferDayCount()
        )
        handleIndependentMode(dataSelectRecyclerViewAdapter, position, date)
    }

    /**
     * 获取起始日期与结束日期之间相隔的天数
     */
    private fun getDifferDayCount(): Int {
        val startDate = startDate ?: return 0
        val endDate = endDate ?: return 0
        return startDate.differDay(endDate)
    }
}
